// package com.qqt.csr.web.service;
//
// import com.google.common.base.Stopwatch;
// import com.google.common.collect.Lists;
// import com.qqt.csr.common.acl.aics.AICustomerServiceClient;
// import com.qqt.csr.common.utils.CacheKeyUtil;
// import com.qqt.csr.web.dto.member.CustomerServiceInfoDTO;
// import com.qqt.csr.web.entity.SkillSetConfig;
// import com.qqt.csr.web.enums.RoutePolicyEnum;
// import lombok.extern.slf4j.Slf4j;
// import org.apache.commons.collections.CollectionUtils;
// import org.apache.commons.collections.MapUtils;
// import org.redisson.api.RScript;
// import org.redisson.api.RedissonClient;
// import org.springframework.beans.factory.annotation.Autowired;
// import org.springframework.beans.factory.annotation.Value;
// import org.springframework.stereotype.Service;
//
// import java.util.List;
// import java.util.Map;
// import java.util.Random;
// import java.util.concurrent.TimeUnit;
// import java.util.concurrent.atomic.AtomicInteger;
//
// /**
//  * 客服路由服务
//  *
//  * @author
//  */
// @Slf4j
// // @Service
// public class RouteCsService {
//     private static final String ALLOCATE_LIMIT_SCRIPT = "local cv = redis.call('INCRBY', KEYS[1], 0);if cv+tonumber(ARGV[2]) <= tonumber(ARGV[1]) then return redis.call('INCRBY', KEYS[1], ARGV[2]);else return 0;end;";
//     private static final String RELEASE_ALLOCATED_SCRIPT = "local cv = redis.call('INCRBY', KEYS[1], 0);if cv <= tonumber(ARGV[1]) then redis.call('DEL', KEYS[1]);else redis.call('INCRBY', KEYS[1], -ARGV[1]);end;return 1;";
//
//     @Autowired
//     private RedissonClient redissonClient;
//
//     /**
//      * 根据客服接入策略，获取在线客服
//      *
//      * @param skillSetConfig
//      * @param onlineCsList
//      * @return 返回null标识无在线客服
//      */
//     public CustomerServiceInfoDTO route(SkillSetConfig skillSetConfig, List<CustomerServiceInfoDTO> onlineCsList) {
//         if (CollectionUtils.isEmpty(onlineCsList)) {
//             return null;
//         }
//
//         List<CustomerServiceInfoDTO> csList = Lists.newArrayList(onlineCsList);
//
//         if (RoutePolicyEnum.RANDOM.getValue().equals(skillSetConfig.getRoutePolicy())) {
//             do {
//                 CustomerServiceInfoDTO cs = doRouteByRandom(csList);
//                 if (allocate(cs, 1)) {
//                     return cs;
//                 } else {
//                     csList.remove(cs);
//                 }
//             } while (CollectionUtils.isNotEmpty(csList));
//         }
//
//         return null;
//     }
//
//     /**
//      * 释放客服进线被占用的访客名额
//      *
//      * @param csId
//      */
//     public void release(Long csId, int releaseCount) {
//         String redisKey = String.format(CacheKeyUtil.SkillSet.CS_CHAT_VISITOR_COUNT, csId);
//         redissonClient.getScript().eval(
//                 RScript.Mode.READ_WRITE,
//                 RELEASE_ALLOCATED_SCRIPT,
//                 RScript.ReturnType.VALUE,
//                 Lists.newArrayList(redisKey),
//                 releaseCount
//         );
//     }
//
//     /**
//      * 释放客服进线被占用的访客名额
//      *
//      * @param releaseMap
//      */
//     public void release(Map<Long, AtomicInteger> releaseMap) {
//         if (MapUtils.isEmpty(releaseMap)) {
//             return;
//         }
//         releaseMap.forEach((csId, releaseCount) -> {
//             if (releaseCount.get() <= 0) {
//                 return;
//             }
//             release(csId, releaseCount.get());
//         });
//     }
//
//     private CustomerServiceInfoDTO doRouteByRandom(List<CustomerServiceInfoDTO> csList) {
//         return csList.get(new Random().nextInt(csList.size()));
//     }
//
//     /**
//      * 给当前客服分配进线访客
//      *
//      * @param cs
//      * @return
//      */
//     private boolean allocate(CustomerServiceInfoDTO cs, int allocatedCount) {
//         String redisKey = String.format(CacheKeyUtil.SkillSet.CS_CHAT_VISITOR_COUNT, cs.getId());
//         Long result = redissonClient.getScript().eval(
//                 RScript.Mode.READ_WRITE,
//                 ALLOCATE_LIMIT_SCRIPT,
//                 RScript.ReturnType.VALUE,
//                 Lists.newArrayList(redisKey),
//                 cs.getReceptionLimit(), allocatedCount
//         );
//
//         return result > 0;
//     }
// }
